package org.tp;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.FileWriter;



/** fonction permettant de parcourir l'arbre syntaxique**/
public class Parcours {

	AbSynt arbre;
	BufferedWriter buff;
	BufferedWriter oldbuff;
	boolean classe=false;
	String name;
	String mapName;
	int count=1;
	public Parcours(BufferedWriter bf, AbSynt abr)
	{
		arbre = abr;
		buff = bf;
	}


/** permet d'ecrire les arguments d'une fonction lea**/
	public void ecrireArguments(AbSynt abr) throws IOException{
		if(abr.getLeft() != null)
		{
			ecrireArguments(abr.getLeft());

		}
		else{
			if(abr.getTag().toString() == "argument" && abr.getRight()==null){
				if(abr.getType().getEnumType().toString()=="LIST"){
					String type3=new String();

					if(abr.getType().getLeft().getEnumType().toString()=="int"||
							abr.getType().getLeft().getEnumType().toString()=="char"){
						if(abr.getType().getLeft().getEnumType().toString()=="int"){
							type3="Integer"	;
						}
						else{
							type3="Character";
						}
						buff.write("List<"+type3+ "> " + abr.getName());
						buff.flush();
					}

					else{
						buff.write("List<"+abr.getType().getLeft()+ "> " + abr.getName());
						buff.flush();
					}

				}
				else{
					buff.write(abr.getType() + " " + abr.getName());
					buff.flush();
				}
			}
		}
		if (abr.getRight()!= null){
			if(abr.getRight().getTag().toString() == "argument"){
				if(abr.getRight().getType().getEnumType().toString()=="LIST"){
					String type3=new String();

					if(abr.getRight().getType().getLeft().getEnumType().toString()=="int"||
							abr.getRight().getType().getLeft().getEnumType().toString()=="char"){
						if(abr.getRight().getType().getLeft().getEnumType().toString()=="int"){
							type3="Integer"	;
						}
						else{
							type3="Character";
						}
						buff.write(", List<"+type3+ "> " + abr.getRight().getName());
						buff.flush();
					}

					else{
						buff.write(", List<"+abr.getRight().getType().getLeft()+ "> " + abr.getRight().getName());
						buff.flush();
					}

				}
				else{
					//IDEM LIST POUR MAP
					buff.write(","+abr.getRight().getType() + " " + abr.getRight().getName());
					buff.flush();
				}

			}
		}
	}

	/** ecrit l'arbre ayant pour tag LIST, separant par une "," les elements  **/
	public void ecrireList(AbSynt abr) throws IOException{
		if(abr.getTag() != EnumTag.LIST)
		{
			buff.write(abr.getName());
			buff.flush();

		}
		else{
			buff.write(", " +abr.getRight().getName());
			buff.flush();
		}
	}

	/** ecris les appels de fonction, id(argument)**/
	public void ecrireAplFct(AbSynt abr) throws IOException{
		ecrireVar(abr.getLeft());

		buff.write("(");
		buff.flush();
		if(abr.getRight() != null)
			//ecrireList(abr.getRight());
			ecrireVar(abr.getRight());
		buff.write(")");

		buff.flush();
	}

	/**  ecris les variables en fonction de la forme de l'arbre (VARIABLE DE STRUCT, , ...) **/
	public void ecrireVariable(AbSynt abr) throws IOException{
		if(abr.getType() != null){ //si la variable à un type c'est une déclaration, on récupère le type
			buff.write(abr.getType() + " ");
			buff.flush();
		}
		if(abr.getLeft() == null){ //soit il n'a aucun fils : pratiquement toutes les variables, voir s'il y a d'autres cas à discerner
			buff.write(abr.getName());
			buff.flush();
		}
		else if(abr.getRight() == null){ //soit il en a qu'un fils gauche : tableau
			ecrireVar(abr.getLeft());
		}
		else{ //soit il a 2 fils : variable de classe
			ecrireVar(abr.getLeft());
			buff.write(".");
			buff.flush();
			ecrireVar(abr.getRight());
		}
	}

	/** ecris les expressions suivants le tag de l'arbre + variable**/
	public void ecrireVar(AbSynt abr) throws IOException{
		switch (abr.getTag()){
		case INTEGER:
		case REAL:
		case BOOL:
		case CONST:
		case CHAR:
			buff.write(abr.getName());
			buff.flush();
			break;
		case STRING:
			buff.write("\"" + abr.getName() + "\"");
			buff.flush();
			break;
		case PLUS:
			ecrireVar(abr.getLeft());
			buff.write(" + ");
			buff.flush();
			ecrireVar(abr.getRight());
			break;
		case MINUS:
			ecrireVar(abr.getLeft());
			buff.write(" - ");
			buff.flush();
			ecrireVar(abr.getRight());
			break;
		case NO:
			buff.write("!"); //TO DO
			ecrireVar(abr.getLeft());
			buff.flush();
			break;
		case MINUS_U:
			buff.write("-"); //TO DO
			ecrireVar(abr.getLeft());
			buff.flush();
			break;
		case MULT:
			ecrireVar(abr.getLeft());
			buff.write(" * ");
			buff.flush();
			ecrireVar(abr.getRight());
			break;
		case DIV:
			ecrireVar(abr.getLeft());
			buff.write(" / ");
			buff.flush();
			ecrireVar(abr.getRight());
			break;
		case MOD:
			ecrireVar(abr.getLeft());
			buff.write(" % ");
			buff.flush();
			ecrireVar(abr.getRight());
			break;
		case EQ:
			ecrireVar(abr.getLeft());
			buff.write(" == ");
			buff.flush();
			ecrireVar(abr.getRight());
			break;
		case OR:
			ecrireVar(abr.getLeft());
			buff.write(" || ");
			buff.flush();
			ecrireVar(abr.getRight());
			break;
		case AND:
			ecrireVar(abr.getLeft());
			buff.write(" && ");
			buff.flush();
			ecrireVar(abr.getRight());
			break;
		case DIFF :
			ecrireVar(abr.getLeft());
			buff.write(" != ");
			buff.flush();
			ecrireVar(abr.getRight());
			break;
		case LE:
			ecrireVar(abr.getLeft());
			buff.write(" <= ");
			buff.flush();
			ecrireVar(abr.getRight());
			break;
		case LT:
			ecrireVar(abr.getLeft());
			buff.write(" < ");
			buff.flush();
			ecrireVar(abr.getRight());
			break;
		case GE:
			ecrireVar(abr.getLeft());
			buff.write(" >= ");
			buff.flush();
			ecrireVar(abr.getRight());
			break;
		case GT:
			ecrireVar(abr.getLeft());
			buff.write(" > ");
			buff.flush();
			ecrireVar(abr.getRight());
			buff.flush();
			break;
		case VAR:
			ecrireVariable(abr);
			break;
		case NULL:
			buff.write("null");
			buff.flush();
			break;
		case DECR:
			ecrireVar(abr.getLeft());
			buff.write("--");
			buff.flush();
			break;
		case INC:
			ecrireVar(abr.getLeft());
			buff.write("++");
			buff.flush();
			break;
		case TAB:
			//System.out.println("TABLEAU");
			ecrireVar(abr.getLeft());
			buff.write("[");
			buff.flush();
			ecrireVar(abr.getRight());
			buff.write("]");
			buff.flush();
			break;
		case APFCT:
			buff.flush();
			ecrireAplFct(abr);
			break;
		case ARG:
			if(abr.getLeft().getTag()==EnumTag.ARG){
				ecrireVar(abr.getLeft());
			}
			else{
				//if(abr.getLeft().getTag()==EnumTag.MINUS_U)
				//buff.write(abr.getLeft().getName());
				ecrireVar(abr.getLeft());
			}
			if(abr.getRight()!=null){
				buff.write(",");
				ecrireVar(abr.getRight());
				//buff.write(abr.getRight().getName());
			}
			break;

		case MAP: 
			if(abr.getLeft().getTag()==EnumTag.MAP){
				ecrireVar(abr.getLeft());
			}
			else{
				buff.write("\n\t"+mapName+".put");
				ecrireVar(abr.getLeft());
			}
			if(abr.getRight()!=null){
				buff.write("\n\t"+mapName+".put");
				ecrireVar(abr.getRight());
			}
			break;
		case SET: 
			if(abr.getLeft().getTag()!=EnumTag.SET){
				buff.write("\t"+mapName+".add(");
				ecrireVar(abr.getLeft());
				buff.write(");\n");

			}
			else{
				ecrireVar(abr.getLeft());
			}
			if(abr.getRight()!=null){
				buff.write("\t"+mapName+".add(");
				ecrireVar(abr.getRight());
				buff.write(");\n");

			}

			break;
		case LIST:
			buff.write("(");
			ecrireVar(abr.getLeft());
			buff.write(",");
			if(abr.getRight()!=null){
				ecrireVar(abr.getRight());
			}
			buff.write(");");

			break;
		case ENUM :
			System.out.println("TYPE NON IMPLEMENTE : ENUM");
			break;
		default:
			System.out.println("\nvar inconnue au bataillon : \n" + abr.getTag());
			break;

		}

	}

	/** ecris les affectation suivant le tag **/
	public void ecrireAff(AbSynt abr) throws IOException{
		AbSynt tmp=abr;
		while (tmp.getLeft()!=null){
			tmp=tmp.getLeft();//On va chercher au plus profond	
		}
		String name=tmp.getName(); //On recupere son nom;
		if(!Main.varGlob.getAlloc(name)){

			//FAUT ALLOUER
			Main.varGlob.setAlloc(name);
			AllouerVariable(name);

		}
		if(abr.getRight().getTag()==EnumTag.MAP || abr.getRight().getTag()==EnumTag.SET){
			mapName = abr.getLeft().getName();
			ecrireVar(abr.getRight());
			buff.write("\n");
			buff.flush();
		}
		else{

			buff.write("\t\t\t");
			buff.flush();
			ecrireVar(abr.getLeft());
			buff.write(" = ");

			buff.flush();
			ecrireVar(abr.getRight());
			abr.setRight(null);
			buff.write(";\n");
			buff.flush();
		}
	}

	/** Ecrire le corps d'une fonctions, declarations et instruction**/
	public void ecrireFct(AbSynt abr) throws IOException{

		switch(abr.getTag())
		{
		case AFF:
			ecrireAff(abr);
			break;
		case RET:
			buff.write("\t\t\treturn "); 
			ecrireVar(abr.getLeft()) ;
			buff.write(";\n");
			buff.flush();
			break;
		case DECL:
			if(abr.getLeft().getTag() == EnumTag.TAB){
				buff.write("\t\t"+abr.getLeft().getType() + "[");
				ecrireVar(abr.getLeft().getLeft().getRight());
				buff.write("] "+abr.getLeft().getLeft().getLeft().getName()+"= new "+abr.getLeft().getType()+"[");
				ecrireVar(abr.getLeft().getLeft().getRight());
				buff.write("];\n");
				buff.flush();
			}
			if(abr.getLeft().getTag() == EnumTag.VAR){

				parcoursDeclLoc(abr);
				/*buff.write("\t\t"+abr.getLeft().getType() + " " + abr.getLeft().getName() + ";\n");
				buff.flush();*/
			}

			break;
		case FOR:
			buff.write("\t for(");
			if(abr.getLeft().getRight().getTag()==EnumTag.FORTYPE){
				ecrireVariable(abr.getLeft().getLeft());

				//buff.write("\tje vais me faire chie");
				buff.write("=");
				buff.write(abr.getLeft().getRight().getLeft().getName());
				buff.write("; ");
				ecrireVariable(abr.getLeft().getLeft());
				buff.write("<");
				ecrireVar(abr.getLeft().getRight().getRight());
				buff.write("; ");
				ecrireVariable(abr.getLeft().getLeft());
				buff.write("++ ");
			}
			else if(abr.getLeft().getRight().getTag()==EnumTag.VAR){
				String type=abr.getLeft().getRight().getType().toString();
				if(type.equals("String")){
					type="char ";
					//buff.write("char ");

				}
				if(type.equals("MAP")){
					type=abr.getLeft().getRight().getType().getRight().toString()+" ";

				}
				if(type.equals("LIST")){
					type=abr.getLeft().getRight().getType().getLeft().toString()+" ";
				}

				buff.write (type+"\t");
				ecrireVariable(abr.getLeft().getLeft());
				buff.write ("\t : \t");
				//buff.write(abr.getLeft().get)
				ecrireVar(abr.getLeft().getRight().getLeft());
			}
			buff.write("\t ) {\n");

			ecrireFct(abr.getRight());
			abr.setRight(null);/*CRADEEEEEEE*/
			buff.write("\t  }\n");
			buff.flush();
			break;
		case WHILE:
			buff.write("\t while( " );
			ecrireVar(abr.getLeft());
			buff.write("){\n");
			buff.flush();
			ecrireFct(abr.getRight());
			buff.write("\t}\n");
			abr.setRight(null); /*CRADEEEEEEE*/
			break;
		case REPEAT:
			buff.write("\t do {\n");
			ecrireFct(abr.getLeft());
			abr.setLeft(null);
			buff.write("}");
			buff.write("\t while(");
			ecrireVar(abr.getRight().getLeft());
			buff.write("\t );\n");
			buff.flush();
			abr.setRight(null);
			break;
		case IF:
			buff.write("\t if( " );
			ecrireVar(abr.getLeft());
			buff.write("){\n");
			if(abr.getRight().getTag()==EnumTag.THENELSE){
				ecrireFct(abr.getRight().getLeft());
				buff.write("\t}\n");
				buff.write("\telse{\n");
				ecrireFct(abr.getRight().getRight());
				buff.write("\t}\n");
				abr.setRight(null);
				abr.setLeft(null);
			}
			else{
				ecrireFct(abr.getRight());
				buff.write("}\n");
				abr.setRight(null);
			}
			buff.flush();
			break;
		case BREAK:
			buff.write("\t break;\n");
			buff.flush();
			break;
		case VARINST:

			if(abr.getLeft().getTag()!=EnumTag.VARINST){
				buff.write("\t case "+abr.getLeft().getName()+":\n");
				buff.flush();
			}
			//else{
			//	ecrireFct(abr.getLeft());

			//}
			break;
		case CASE:
			/*CAS CASE OF NON TRAITEE*/
			buff.write("\t switch (");
			ecrireVar(abr.getLeft());
			buff.write("){\n");
			ecrireFct(abr.getRight());
			buff.write("}\n");
			buff.flush();
			abr.setRight(null);
			break;

		case PRINT :
			buff.write("\t System.out.println(");
			buff.flush();
			if(abr.getLeft().getTag()!=EnumTag.PT){
				ecrireVar(abr.getLeft());
			}
			else{
				ecrireFct(abr.getLeft());
			}
			buff.write(");\n");
			abr.setLeft(null);
			buff.flush();
			break;
		case READ : 
			buff.write("\t Scanner sc"+count +"= new Scanner(System.in);\n "+
					"System.out.println(\"Veuillez saisir un mot :\");\n");
			ecrireVar(abr.getLeft());
			buff.write("= sc"+count+".nextLine();\n");
			count++;
			abr.setLeft(null);
			//abr.setLeft(null);
			break;
		case PT:
			if(abr.getRight()!=null){
				ecrireVar(abr.getLeft());
				buff.write("+");
			}

			if(abr.getRight().getTag()==EnumTag.PT){
				ecrireFct(abr.getLeft());

			}
			else{
				ecrireVar(abr.getRight());	

			}
			break;
		case APFCT:
			ecrireAplFct(abr);
			buff.write(";\n");	

			break;
		default:
			break;
		}
		if(abr.getLeft()!=null)
			ecrireFct(abr.getLeft());
		if(abr.getRight()!=null)
			ecrireFct(abr.getRight());
	}

	/** ecris une fonction en complet, type_ret id(arg){ corps }, 
	 * gere le type de fonction static ou non en fonction de sa place  **/
	public void parcoursFonction(AbSynt abr) throws IOException
	{
		AbSynt tmp = abr.getLeft().getLeft();
		switch(abr.getTag()){
		case CONSTRU:
			buff.write("\t\tpublic " + name + "(");
			buff.flush();	
			if(abr.getLeft().getLeft().getRight()!=null)
				ecrireArguments(abr.getLeft().getLeft().getRight());
			buff.write("){\n");
			buff.flush();
			ecrireFct(abr.getRight());
			buff.write("\t\t}\n");
			buff.flush();
			break;
		case FCT:
		case OP: //operator à revoir

			if(tmp.getType()!=null)
				if(tmp.getName().equals("main")){
					buff.write("\t\t public static"+tmp.getType()+" main(String[] args){\n");
				}
				else{
					//System.out.println("TEST CLASSE");

					if(classe==false){
						buff.write("\t\t static ");
					}
					else{
						buff.write("\t\t");
					}
					buff.write("public "+ tmp.getType()+" "+tmp.getName()+ "(");
					if(abr.getLeft().getRight()!=null)
						ecrireArguments(abr.getLeft().getRight());
					buff.write(") {\n");
				}
			else
				if(tmp.getName().equals("main")){
					buff.write("\t\t public static void main(String[] args){\n");
				}
				else{
					//System.out.println("TEST CLASSE");
					if(classe==false){
						buff.write("\t\t static");
					}
					else{
						buff.write("\t\t");
					}
					buff.write(" public void "+tmp.getName()+ "(");
					if(abr.getLeft().getRight()!=null)
						ecrireArguments(abr.getLeft().getRight());
					buff.write(") {\n");
				}
			buff.flush();
			ecrireFct(abr.getRight());
			buff.write("\t\t}\n");
			buff.flush();
			break;
		default:
			System.out.println("Erreur dans le type de parcoursFct, non géré : "+abr.getLeft().getTag());
			break;
		}

	}


	/** parcours des fonction dans la classe **/
	public void parcoursFct(AbSynt abr)throws IOException
	{
		if(abr.getRight()!=null){ //si y'a un fils droit ce n'est pas 1ere fonction
			parcoursFct(abr.getLeft()); //on descend dans le fils gauche
			parcoursFonction(abr.getRight());
		}
		else {
			parcoursFonction(abr.getLeft());
		}
	}


	/**parcours d'une classe **/
	public void parcoursClass(AbSynt abr) throws IOException
	{
		if(abr.getTag().toString() == "declaration")
		{
			/*buff.write("\t\t"+abr.getLeft().getType() + " " + abr.getLeft().getName() + ";\n");
			buff.flush();*/
			parcoursDeclLoc(abr);

		}
		else if(abr.getTag().toString() == "Fonction")
		{
			parcoursFct(abr);
			return ;
		}
		if(abr.getRight()!=null)
			parcoursClass(abr.getRight());
	}

	/** decide et ecris si besoin l'allocation d'une variable globale lors d'une affectation**/

	public void AllouerVariable(String name)throws IOException{  
		/*ATTENTION AVEC INT ET CHAR*/

		Type type=Main.varGlob.getVar(name).getType();

		if (type.getEnumType().toString()=="type def"){

			buff.write("\t "+ Main.varGlob.getVar(name).getid());
			buff.write(" = new "+Main.varGlob.getVar(name).getType() +"();\n ");
			buff.flush();
			return;
		}
		if (type.getEnumType().toString()=="MAP"){
			String type1=new String();
			String type2=new String();
			type2=Main.varGlob.getVar(name).getType().getRight().toString();
			type1=Main.varGlob.getVar(name).getType().getLeft().toString();
			if(type1.equals("int")||type1.equals("char")){
				if(type1.equals("int")){
					type1="Integer";
				}
				else{
					type1="Character";
				}
			}
			if(type2.equals("int")||type2.equals("char")){
				if(type2.equals("int")){
					type2="Integer";
				}
				else{
					type2="Character";
				}
			}
			buff.write("\t "+ name);
			buff.write(" = new HashMap<"+type1+","+type2+ ">(); \n");
			buff.flush();
			return;
		}
		if(type.getEnumType().toString()=="String"){
			buff.write(name +"= new String();\n ");
			buff.flush();
			return;
		}
		if (type.getEnumType().toString()=="SET"){
			String type1=Main.varGlob.getVar(name).getType().getLeft().toString();
			if(type1.equals("int")||type1.equals("char")){
				if(type1.equals("int")){
					type1="Integer";
				}
				else{
					type1="Character";
				}
			}
			buff.write("\t "+ name);
			buff.write(" = new HashSet<"+type1+">(); \n");
			buff.flush();
			return;
		}
		if (type.getEnumType().toString()=="LIST"){
			String type1=Main.varGlob.getVar(name).getType().getLeft().toString();
			if(type1.equals("int")||type1.equals("char")){
				if(type1=="int"){
					type1="Integer";
				}
				else{
					type1="Character";
				}
			}
			buff.write("\t "+ name);
			buff.write(" = new ArrayList<"+type1+ ">();\n");
			buff.flush();
			return;
		}
		buff.write("ALLOCATION : "+type.toString());
		buff.flush();

	}





/** parcours et ecriture des declarations locales**/
	public void parcoursDeclLoc(AbSynt abr) throws IOException{

		if(abr.getLeft() != null)
		{
			if(abr.getLeft().getTag() == EnumTag.AFF)
				ecrireAff(abr.getLeft());
			else
				parcoursDeclLoc(abr.getLeft());

		}
		else{
			if(abr.getTag().toString() == "variable"){
				if(abr.getType().getEnumType().toString() == "type def"){
					buff.write("\t"+abr.getType().getId()+" "+abr.getName() + " = new "+abr.getType().getId()+ "();\n");
					buff.flush();
				}
				else{
					if(abr.getType().getEnumType().toString()=="TAB"){
						//System.out.println("TABLEAU\n");
					}

					if(abr.getType().getEnumType().toString() == "MAP"){
						String type1=new String();
						String type2=new String();

						if(abr.getType().getLeft().getEnumType().toString()=="int"||
								abr.getType().getLeft().getEnumType().toString()=="char"){
							if(abr.getType().getLeft().getEnumType().toString()=="int"){
								type1="Integer"	;
							}
							else{
								type1="Character";
							}
							if(abr.getType().getRight().getEnumType().toString()=="int"||
									abr.getType().getRight().getEnumType().toString()=="char"){
								if(abr.getType().getRight().getEnumType().toString()=="int"){
									type2="Integer"	;
								}
								else{
									type2="Character";
								}
								buff.write("\t HashMap<"+type1+","+type2 + "> " + abr.getName());
								buff.write(" = new HashMap<"+type1+","+type2 + ">();\n ");
								buff.flush();
							}
							else{
								buff.write("\t HashMap<"+type1+","+abr.getType().getRight() + "> " + abr.getName());
								buff.write(" = new HashMap<"+type1+","+abr.getType().getRight() + ">(); \n ");
								buff.flush();
							}
						}
						else{
							if(abr.getType().getRight().getEnumType().toString()=="int"||
									abr.getType().getRight().getEnumType().toString()=="char"){
								if(abr.getType().getRight().getEnumType().toString()=="int"){
									type2="Integer"	;
								}
								else{
									type2="Character";
								}
								buff.write("\t HashMap<"+abr.getType().getLeft()+","+type2 + "> " + abr.getName());
								buff.write(" = new HashMap<"+abr.getType().getLeft()+","+type2 + ">(); \n ");
								buff.flush();
							}
							else{
								buff.write("\t HashMap<"+abr.getType().getLeft()+","+abr.getType().getRight() + "> " + abr.getName());
								buff.write(" = new HashMap<"+abr.getType().getLeft()+","+abr.getType().getRight() + ">(); \n ");
								buff.flush();
							}
						}
					}
					else{ if(abr.getType().getEnumType().toString() == "SET"){
						String type1=new String();
						if(abr.getType().getLeft().getEnumType().toString()=="int"||
								abr.getType().getLeft().getEnumType().toString()=="char"){
							if(abr.getType().getLeft().getEnumType().toString()=="int"){
								type1="Integer"	;
							}
							else{
								type1="Character";
							}
							buff.write("\t Set<"+type1+ "> " + abr.getName());
							buff.write(" = new HashSet<"+type1+">(); \n ");
							buff.flush();
						}
						else{
							buff.write("\t Set<"+abr.getType().getLeft()+ "> " + abr.getName());
							buff.write(" = new HashSet<"+abr.getType().getLeft() + ">(); \n ");
							buff.flush();
						}

					}
					else{
						if(abr.getType().getEnumType().toString() == "LIST"){
							String type3=new String();
							if(abr.getType().getLeft().getEnumType().toString()=="int"||
									abr.getType().getLeft().getEnumType().toString()=="char"){
								if(abr.getType().getLeft().getEnumType().toString()=="int"){
									type3="Integer"	;
								}
								else{
									type3="Character";
								}
								buff.write("\t List<"+type3+ "> " + abr.getName());
								buff.write(" = new ArrayList<"+type3+">();\n ");
								buff.flush();
							}
							else{
								buff.write("\t List<"+abr.getType().getLeft()+ "> " + abr.getName());
								buff.write(" = new ArrayList<"+abr.getType().getLeft() + ">(); \n ");
								buff.flush();
							}

						}
						else{
							buff.write("\t "+abr.getType() + " " + abr.getName() + ";\n");
							buff.flush();}
					}
					}
				}
			}
		}
		if (abr.getRight()!= null){
			if(abr.getRight().getTag().toString() == "variable"){
				buff.write("\t\t"+abr.getRight().getType() + " " + abr.getRight().getName() + ";\n");
				buff.flush();
			}
		}

	}

	/** parcours et ecritures des declarations globale dans l'arbre **/	
	public void parcoursDecl(AbSynt abr) throws IOException
	{

		switch(abr.getTag())
		{ 
		case CONST:
			buff.write("\t static final "+abr.getRight().getType()+" "+abr.getLeft().getName() +"="+abr.getRight().getName()+";\n");
			break;
		case AFF:
			buff.write("\t static "+abr.getLeft().getType() + " " + abr.getLeft().getName() + " = " +  abr.getRight().getName() + ";\n");
			buff.flush();
			break;
		case VAR:
			if(abr.getType().getEnumType().toString() == "type def"){
				buff.write("\t static "+abr.getType().getId()+" "+abr.getName() +";\n");
				buff.flush();
			}
			else{
				if(abr.getType().getEnumType().toString()=="ENUM"){
					System.out.println("TYPE NON IMPLEMENTE, ENUM\n");

					/*ENUMERATION PUBLIC ENUM abr.getName() { elem1, elem2 ...}*/
				}
				else{
					if(abr.getType().getEnumType().toString() == "MAP"){
						String type1=abr.getType().getLeft().getEnumType().toString();
						String type2=abr.getType().getRight().getEnumType().toString();

						if(type1=="int"||
								type1=="char"){
							if(type1=="int"){
								type1="Integer"	;
							}
							else{
								type1="Character";
							}
						}
						if(type2=="int"||
								type2=="char"){
							if(type2=="int"){
								type2="Integer"	;
							}
							else{
								type2="Character";
							}
						}
						buff.write("\t static HashMap<"+type1+","+type2 + "> " + abr.getName()+";\n");
						buff.flush();
					}
					else{ 
						if(abr.getType().getEnumType().toString() == "SET"){
							String type1=new String();
							if(abr.getType().getLeft().getEnumType().toString()=="int"||
									abr.getType().getLeft().getEnumType().toString()=="char"){
								if(abr.getType().getLeft().getEnumType().toString()=="int"){
									type1="Integer"	;
								}
								else{
									type1="Character";
								}
								buff.write("\t static Set<"+type1+ "> " + abr.getName()+";\n");
								buff.flush();
							}
							else{
								buff.write("\t static Set<"+abr.getType().getLeft()+ "> " + abr.getName()+";\n");
								buff.flush();
							}

						}
						else{
							if(abr.getType().getEnumType().toString() == "LIST"){
								String type3=new String();
								if(abr.getType().getLeft().getEnumType().toString()=="int"||
										abr.getType().getLeft().getEnumType().toString()=="char"){
									if(abr.getType().getLeft().getEnumType().toString()=="int"){
										type3="Integer"	;
									}
									else{
										type3="Character";
									}
									buff.write("\t static List<"+type3+ "> " + abr.getName()+";\n");
									buff.flush();
								}
								else{
									buff.write("\t static List<"+abr.getType().getLeft()+ "> " + abr.getName()+";\n");
									buff.flush();
								}
							}
							else{buff.write("\t static"+abr.getType() + " " + abr.getName() + ";\n");
							buff.flush();}
						}
					}
				}	
			}
			break;
		case STRUCT:
			buff.write("\n\t static class " + abr.getLeft().getName() + "{\n ");
			buff.flush();
			parcoursDeclLoc(abr.getRight());
			buff.write("\n\t}\n\n");
			buff.flush();
			break;
		case CLASS:
			classe=true;
			oldbuff=buff;
			buff= new BufferedWriter(new FileWriter("./"+abr.getLeft().getName()+".java"));
			buff.write("\n\t public class " + abr.getLeft().getName() + "{\n ");
			buff.flush();
			name = abr.getLeft().getName();
			parcoursClass(abr.getRight());
			buff.write("\n\t}\n\n");
			buff.flush();
			buff=oldbuff;
			classe=false;

			break;
		case PROTO :
			System.out.println("WARNING : les prototypes ne sont pas traites, " +
					"verifier votre fichier");
			break;
		default:
			System.out.println("Erreur de tag dans parcoursDecl, tag non reconnu : "+ abr.getTag());
		}	
	}


	/** Parcours de l'arbre complet et donc du fichier complet**/
	public void parcours() throws IOException{
		if(arbre.getTag() != null)
		{
			while(arbre.getTag().toString() == "declaration")
			{
				parcoursDecl(arbre.getLeft());
				arbre = arbre.getRight();
			}
			if(arbre.getTag().toString() == "Fonction")
			{
				parcoursFct(arbre);
			}
		}

	}


}
